package com.example.cycledependency;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.RootBeanDefinition;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class CycleDependency3 {
    private static final Map<String, RootBeanDefinition> beanDefinitionMap = new HashMap<>();
    // 一级缓存，即单例池
    private static final Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
    // 二级缓存，解决getBean(beanName)方法的读写冲突
    private static final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>();


    public static void main(String[] args) throws IllegalAccessException, InstantiationException {
        newApplicationContext();
        getBean("instanceA");
    }

    public static void newApplicationContext() throws InstantiationException, IllegalAccessException {
        // 加载所有的BeanDefinition到beanDefinitionMap中
        loadBeanDefinitions();
        // 遍历definitionMap去创建Bean
        for (String beanName : beanDefinitionMap.keySet()) {
            getBean(beanName);
        }
    }

    public static void loadBeanDefinitions() {
        RootBeanDefinition aBeanDefinition = new RootBeanDefinition(InstanceA.class);
        RootBeanDefinition bBeanDefinition = new RootBeanDefinition(InstanceB.class);
        beanDefinitionMap.put("instanceA", aBeanDefinition);
        beanDefinitionMap.put("instanceB", bBeanDefinition);
    }

    private static Object getBean(String beanName) throws IllegalAccessException, InstantiationException {
        // 若一级缓存中有，说明已创建，直接返回
        if (singletonObjects.containsKey(beanName)) {
            return singletonObjects.get(beanName);
        }
        synchronized (singletonObjects) {
            // 如果一级缓存读不到，再从二级缓存当中读：
            // instanceA->instanceB，instanceB->instanceA(此时一级缓存还没有成品instanceA，要从二级缓存中读取半成品instanceA)
            if (earlySingletonObjects.containsKey(beanName)) {
                return earlySingletonObjects.get(beanName);
            }
            // 获取当前BeanDefinition
            RootBeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
            // 实例化Bean
            Class<?> beanClass = beanDefinition.getClass();
            Object beanInstance = beanClass.newInstance();
            // 将半成品放到二级缓存
            earlySingletonObjects.put(beanName, beanInstance);
            // 属性注入(循环依赖)
            // 拿到Class中的所有属性
            Field[] declaredFields = beanClass.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                // 判断当前字段是否有@Autowired注解
                Autowired annotation = declaredField.getAnnotation(Autowired.class);
                // 说明属性有Autowired
                if (annotation != null) {
                    String name = declaredField.getName();
                    Object bean = getBean(name);
                    declaredField.setAccessible(true);
                    declaredField.set(beanInstance, bean);
                }
            }
            // 将成品放到一级缓存
            singletonObjects.put(beanName, beanClass);
            return beanInstance;
        }
    }
}
// 为了解决CycleDependency2的读写冲突问题，创建二级缓存，将半成品放入二级缓存，成品放入到一级缓存
// 对于读操作，调用getBean(beanName)时直接从一级缓存中获取；对于创建时的循环依赖注入才是从二级缓存中获取